#include "MysqlConn.h"

MysqlConn::MysqlConn()
{
    m_conn = mysql_init(nullptr);       // 初始化连接环境，分配数据库内存
    mysql_set_character_set(m_conn, "utf8");    // 设置编码，防止出现乱码
}

MysqlConn::~MysqlConn()
{
    if(m_conn != nullptr)
    {
        mysql_close(m_conn);
    }
    freeResult();
}

/* 连接数据库 */
bool MysqlConn::connect(const string & host, const string & user, const string & passwd, const string & dbname)
{
    unsigned int port = 3306;
    if(mysql_real_connect(m_conn, host.c_str(), user.c_str(), passwd.c_str(), dbname.c_str() , port, NULL, 0) == NULL)
    // 返回一个指针，指向地址和m_conn相同，失败返回空
    {
        std::cerr << "MySQL connection failed: " << mysql_error(m_conn) << std::endl;

        return false;
    }
    //std::cout << "mysql connect success." << std::endl;
    return true;
}

/* 执行sql语句(exec) */
bool MysqlConn::update(const string &sql)
{
    if(mysql_query(m_conn, sql.c_str()))    // 返回0则成功，非0则失败
    {
        // 错误判断 
        std::cout << "file:" << __FILE__ << ",lines:" << __LINE__ << mysql_error(m_conn) << std::endl;
        return false;
    }
    return true;
}

/* 制定Sql查询语句（select）*/
bool MysqlConn::query(const string &sql)
{
    /* 需要清空结果集 */
    freeResult();

    if(mysql_query(m_conn, sql.c_str()))    // 返回0则成功，非0则失败
    {
        // 错误判断 
        std::cout << "file:" << __FILE__ << ",lines:" << __LINE__ << mysql_error(m_conn) << std::endl;
        return false;
    }

    /* 从结果集里面拿取数据，这个函数会把从服务器查询到的结果集到存到客户端 */
    m_result = mysql_store_result(m_conn);
    if(m_result == NULL)
    {
        std::cout << "file:" << __FILE__ << ",lines:" << __LINE__ << mysql_error(m_conn) << std::endl;
        return false;
    }
    return true;
}

bool MysqlConn::next()
{
    if(m_result != nullptr)
    {
        m_row = mysql_fetch_row(m_result);  // 返回的是二级指针， 指向一级指针的地址，结果集
    }
    return false;
}

string MysqlConn::value(int index)
{
    /* 获取列数 */
    int columnCount = mysql_num_fields(m_result);
    if(index >= columnCount || index < 0)
    {
        return string();
    }
    /* 取出index行 */
    char * val = m_row[index];
    /* 求index行字段的长度，mysql_fetch_lengths返回的是一个数组 */
    unsigned long length =  mysql_fetch_lengths(m_result)[index];
    /* 这样就不会以\0为结束符，而是以length来返回string */
    return string(val, length);
}

bool MysqlConn::transaction()
{
    /* 关闭自动提交 */
    return mysql_autocommit(m_conn, false);
}

bool MysqlConn::commit()
{
    return mysql_commit(m_conn);
}

bool MysqlConn::rollback()
{
    return mysql_rollback(m_conn);
}

void MysqlConn::freeResult()
{
    if(m_result)
    {
        mysql_free_result(m_result);
    }
}
void MysqlConn::refreshAliveTime()
{
    /* 空闲的时间起点 */
    m_aliveTime = chrono::steady_clock::now();
}


/* 计算连接存活的总时长 毫秒*/
long long MysqlConn::getAliveTime()
{
    /* 纳秒级 */
    chrono::nanoseconds res = chrono::steady_clock::now() - m_aliveTime;
    /* 精度转换，会损失精度 */
    chrono::milliseconds sec = chrono::duration_cast<chrono::milliseconds>(res);
    /* 返回秒：count（）计算时间间隔中有多少个秒 */
    return sec.count();
}